package code64;

import icg.EQIdent;
import icg.EQTemp;
import icg.ElementQ;
import icg.Quadruple;


import java.util.HashMap;
import java.util.Set;
import java.util.Vector;

import ast.type.OpType;

public class BasicBlock {
	private Vector<Quadruple> block;
	private HashMap<String,Integer> nextUse;
	public static final Integer N = -1;
	public static final Integer S = -2;
	
	public BasicBlock() {
		block = new Vector<Quadruple>();
		nextUse = new HashMap<String, Integer>();
	}
	
	private void set(ElementQ eq){
		if (eq instanceof EQTemp) { // Se temp = nao-vivo
			nextUse.put(eq.toString(), N);
		} else if (eq instanceof EQIdent){ // Se ID = vivo
			nextUse.put(eq.toString(), S);	
		}
		
	}
	
	public void set(ElementQ eq, Integer value) {
		nextUse.put(eq.toString(), value);
	}
	
	public Integer get(ElementQ eq) {
		return nextUse.get(eq);
	}
	
	public void addQuadruple(Quadruple q) {
		block.add(q);
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		for (Quadruple q : block) {
			sb.append(q.toString() + "\n");
		}
		return sb.toString();
	}
	
	public Integer size(){
		return block.size();
	}

	public void setTable() {
		for (Quadruple q : block) {
			if (q.getOp1() != null) {
				set(q.getOp1());
			}
			if (q.getOp2() != null) {
				set(q.getOp2());
			}
			if (q.getRes() != null) {
				set(q.getRes());
			}
		}
		System.out.println("===Before===");
		printTable();
	}
	
	public void printTable(){
		Set<String> key = nextUse.keySet();
		for (String k : key) {
			System.out.println(k + " -> " + nextUse.get(k));
		}
	}
	
	public void buildTable(){
		for (int i = block.size()-1; i>=0; i--) {
			Quadruple q = block.elementAt(i);
			if (q.getOpCode() == OpType.COPY 
					|| q.getOpCode() == OpType.PLUS
					|| q.getOpCode() == OpType.MINUS
					|| q.getOpCode() == OpType.MOD
					|| q.getOpCode() == OpType.MULT
					|| q.getOpCode() == OpType.DIV) {
				if (q.getRes() != null) {
					set(q.getRes(), N);
				}
				if ((q.getOp1() instanceof EQIdent || q.getOp1() instanceof EQTemp) && q.getOp1() != null) {
					set(q.getOp1(), i);
				}
				if ((q.getOp2() instanceof EQIdent || q.getOp2() instanceof EQTemp) && q.getOp2() != null) {
					set(q.getOp2(), i);
				}
			}
		}
		System.out.println("===After===");
		printTable();
	}
}
